package de.dfki.dataSender;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Date;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;

/**
 * Server for streaming accelerometer data. 
 * 
 * @author Markus L�chtefeld (loechti)
 */
public class SensorDataSender implements SensorEventListener {

	private final long SAMPLE_RATE = 30;
	private String serverHost;
	private int serverPort;
	private String deviceId;
	private SensorManager sm;
	private float[] gravity = new float[]{0f,0f,0f};
	private float[] linear_acceleration = new float[]{0f,0f,0f};
	private long previousTime = 0;

	public SensorDataSender(Context context, SensorManager sm, String host, int port, String deviceId) {
		this.serverHost = host;
		this.serverPort = port;
		this.deviceId = deviceId;
		this.sm = sm;
	}

	protected void onResume() {
		Sensor accel = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
		sm.registerListener(this, accel, SensorManager.SENSOR_DELAY_FASTEST);
	}

	protected void onStop() {
		sm.unregisterListener(this);
	}

	public void sendToServer(String message) {
		try {
			InetAddress serverAddr = InetAddress.getByName(serverHost);
			DatagramSocket socket = new DatagramSocket();
			byte[] buf = message.getBytes();
			DatagramPacket packet = new DatagramPacket(buf, buf.length,
					serverAddr, serverPort);
			socket.send(packet);
		} catch (Exception e) {
			// Ignoring errors for now.
		}
	}

	@Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
		//
	}

	@Override
	public void onSensorChanged(SensorEvent event) {
		if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
			long currentTime = new Date().getTime();
			if (currentTime - previousTime >= SAMPLE_RATE) {
				previousTime = currentTime;
				// Filter effects of gravity.	
				final float alpha = 0.8f;
				gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
				gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
				gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
				linear_acceleration[0] = event.values[0] - gravity[0];
				linear_acceleration[1] = event.values[1] - gravity[1];
				linear_acceleration[2] = event.values[2] - gravity[2];

				sendToServer(String.format("%s#%f#%f#%f", deviceId, linear_acceleration[0], 
						linear_acceleration[1], linear_acceleration[2]));
			}
		}		
	}
}
